home *** CD-ROM | disk | FTP | other *** search
/ Skunkware 98 / Skunkware 98.iso / osr5 / sco / scripts / admin / news / cleannews < prev    next >
Encoding:
Korn shell script  |  1997-08-26  |  5.4 KB  |  191 lines

  1. #!/bin/ksh
  2. # @(#) cleannews.ksh 1.1 96/01/20
  3. # 94/11/19 john h. dubois iii (john@armory.com)
  4. # 94/11/21 Remove dirs.  Print running group count.
  5. # 94/12/12 Let group-list be given as 2nd arg.  Allow spool dirs in group-list.
  6. # 96/01/20 Create temp file more carefully
  7.  
  8. Active=/usr/lib/news/active
  9.  
  10. Help="Usage: cleannews save-file [group-list-file]
  11. save-file is a list of groups to save.  If group-list-file is given, it should
  12. contain a list of groups to consider for article removal.  Only the first word
  13. of each line is used.  The word can be a newsgroup name or a spool directory
  14. (relative to /usr/spool/news).  If a group-list-file is not given, the file
  15. $Active is used.  All articles in all groups in the
  16. group-list-file that are not in save-file are removed."
  17.  
  18. case $# in
  19. 1)
  20.     if [ "$1" = -h ]; then
  21.     print "$Help"
  22.     exit 0
  23.     fi
  24.     ;;
  25. 2)
  26.     Active=$2
  27.     ;;
  28. *)
  29.     print -u2 "Wrong number of arguments.  Use -h for help."
  30.     exit 1
  31.     ;;
  32. esac
  33.  
  34. # @(#) mktempfile 1.0 96/05/22
  35. # 96/01/20 jhdiii
  36.  
  37. # Usage: mkfiles name ...
  38. # Creates the named files with some attempt at security.
  39. # This will be more reliable if user do not have chown authority.
  40. # Any file that contains no / characters is created in the user's tempdir.
  41. # If TMP was not set, it is set by this function.
  42. # Returns 0 on success; prints a diagnostic message & returns 1 on failure.
  43. function mkfiles {
  44.     typeset file files
  45.     typeset -i i=0
  46.  
  47.     : ${TMP:=$TMPDIR}
  48.     : ${TMP:=/tmp}
  49.     for file; do
  50.     [[ "$file" != */* ]] && file="$TMP/$file"
  51.     files[i]=$file
  52.     let i+=1
  53.     done
  54.     set -- "${files[@]}"
  55.  
  56.     rm -f "$@" || {
  57.     # hopefully rm will have printed a more specific message.
  58.     print -u2 "Could not remove pre-existing files."
  59.     return 1
  60.     }
  61.     for file; do
  62.     # Use >> to avoid 0'ing the file in case a symlink was just made from
  63.     # the filename to something we don't want to truncate
  64.     >> "$file" || {
  65.         print -u2 "Could not create temp file $file"
  66.         return 1
  67.     }
  68.     # These are very suspicious
  69.     [ -s "$file" ] && {
  70.         print -u2 "New tempfile is not empty!!!"
  71.         return 1
  72.     }
  73.     [ -O "$file" ] || {
  74.         print -u2 "Do not own $file!!!"
  75.         return 1
  76.     }
  77.     done
  78.     # Could do some more stuff here, but anyone concerned with security should
  79.     # have chown authorization off for most users.
  80.     return 0
  81. }
  82.  
  83. # Usage: mktempfile name
  84. # Creates a tempfile name tempdir/#name$$, and sets the global mktempfile_ret
  85. # to that name.  tempdir is a temp directory in $TMP, $TMPDIR, or /tmp, and $$
  86. # is the PID of the current process.
  87. # name should be 8 characters or less, so that the resulting filename will
  88. # not be more than 14 characters long (a limit on some machines).
  89. # Returns 0 on success, prints a diagnostic message & returns 1 on failure.
  90. function mktempfile {
  91.     typeset file="#$1$$"
  92.     mkfiles "$file"
  93.     mktempfile_ret="$TMP/#$1$$"
  94. }
  95.  
  96. name=${0##/}
  97. ClearToEOL=$(tput el)
  98. newsdir=/usr/spool/news
  99. xargsCmd="env - /usr/local/bin/gxargs -n 2000 -P 2 /bin/rm --"
  100. typeset -Z4 groupNum=0
  101. mktempfile clnnews. || {
  102.     print -u2 "$name: Exiting."
  103.     exit 1
  104. }
  105. dirFile=$mktempfile_ret
  106.  
  107. cd $newsdir
  108.  
  109. # start coprocess to keep track of how many files in the undesired groups
  110. # were not cross-posted (had only one link).
  111. # make stat emit filename after link count just so we can detect /dev/null
  112. # when it comes through.
  113. stat -rnfln | awk '
  114. $2 == "/dev/null" {
  115.     printf "%d of %d files had only one link.\n",count,NR | "cat 1>&2"
  116.     exit
  117. }
  118. $1 == 1 {
  119.     count++
  120. }
  121. ' |&
  122.  
  123. # Find all groups in active file that are not in save-groups file and print
  124. # their spool directories
  125. awk -v "active=$Active" '
  126. {
  127.     SaveGroups[$1]
  128. }
  129. END {
  130.     if (NR < 10) {
  131.     print "Only " NR " groups in save file?!" | "cat 1>&2"
  132.     exit 1
  133.     }
  134.     printf "%d groups to be saved.\n",NR | "cat 1>&2"
  135.     close("cat 1>&2")    # flush output
  136.     while ((ret = (getline < active)) == 1) {
  137.     group = $1
  138.     gsub("/",".",group)    # convert paths to newsgroup names
  139.     gsub(/^\.+/,"",group)    # in case paths begin with e.g. ./ or .
  140.     if (!(group in SaveGroups)) {
  141.         gsub(/\./,"/",group)
  142.         print group
  143.     }
  144.     }
  145.     if (ret != 0)
  146.     print "Error reading group-list-file" | "cat 1>&2"
  147. }
  148. ' "$1" | while read dir; do
  149.     let groupNum+=1
  150.     # Echoing filenames w/full group path will require many more 
  151.     if [ -d $newsdir/$dir ] && cd $newsdir/$dir; then
  152.     print $dir >> $dirFile
  153.     print -u2 -n "${ClearToEOL}$groupNum Checking $dir\r"
  154.     # Pattern ?(+([0-9])|.thread) does not work
  155.     set -- +([0-9])
  156.     [[ $1 = \+* ]] && set --
  157.     [ -f .thread ] && set -- "$@" .thread
  158.     if [ $# -gt 0 ]; then
  159.         print -u2 "Removing $# file(s) from $dir"
  160.         # If removing these files with full group path would require
  161.         # more than two invokations of rm, do a special gxargs/rm
  162.         # from the group dir for it.
  163.         if [ $(( (${#dir}+1)*$# )) -gt 10000 ]; then
  164.         print -- "$*" | $xargsCmd
  165.         for file; do
  166.             print -p $dir/$file
  167.         done
  168.         else
  169.         for file; do
  170.             print -- $dir/$file
  171.             print -p $dir/$file
  172.         done
  173.         fi
  174.     fi
  175.     fi
  176.     # jobs > /dev/null 2>&1    # work around accumulating jobs ksh bug
  177. done | $xargsCmd
  178. # use gxargs because it takes arbitrarily long input lines and uses max command
  179. # line space.  -P 2 tells it to start up to 2 processes at a time.
  180. # Get rid of environment to leave more room for cmd line args.
  181.  
  182. # Doesn't seem to be any way of closing pipe to coprocess.
  183. # So, use /dev/null as the eof marker.
  184. print -p /dev/null
  185.  
  186. print -u2 "\nRemoving directories..."
  187. cd $newsdir
  188. # Reverse sort to ensure that lowest dirs come first
  189. sort -r $dirFile |
  190. env - /usr/local/bin/gxargs -n 2000 -P 2 /bin/rmdir -- 2>/dev/null
  191.